// Copyright 2007-2010 Comdiv (F. Sadykov) - http://code.google.com/u/fagim.sadykov/
// Supported by Media Technology LTD 
//  
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//  
//      http://www.apache.org/licenses/LICENSE-2.0
//  
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 
// MODIFICATIONS HAVE BEEN MADE TO THIS FILE
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Xml.XPath;
using Comdiv.Extensions;
using Comdiv.Logging;

namespace Comdiv.Doc{
    public class PrepareNamespacesAndTypesStep : DocumentProcessorStep<PrepareNamespacesAndTypesStep>{
        private ILog log = logger.get<PrepareNamespacesAndTypesStep>();
        protected override void internalProcess(DocumentQuery query){
            MyQuery = query;
            foreach (var lib in MyQuery.Libs){
                foreach (var type in lib.Assembly.GetTypes()){
                    if (type.IsPublic){
                        //Console.WriteLine(type.FullName);
                        var ns = type.Namespace;
                        if (!MyQuery.Types.ContainsKey(ns)){
                            log.Info("namespace added: "+ns);
                            MyQuery.Types[ns] = new List<TypeDescriptor>();
                        }
                        var normalname = Regex.Match(type.FullName, @"^[\w\.]+").Value;
                        var typexpath = "//member[starts-with(@name,'T:{0}')]"._format(normalname);
                        var memberxpath =
                            "//member[starts-with(@name,'M:{0}') or starts-with(@name,'P:{0}')]"._format(normalname);
                        var desc = new TypeDescriptor{Type = type};
                        var xdoc = new XElement("doc");
                        var libdoc = MyQuery.Libs.FirstOrDefault(x => x.Assembly == type.Assembly).Documentation;
                        xdoc.Add(
                            new XElement("type", (libdoc.XPathSelectElement(typexpath) ?? new XElement("x")).Elements(),
                                         new XElement("members",
                                                      from e in libdoc.XPathSelectElements(memberxpath)
                                                      select new XElement("member",
                                                                          new XAttribute("name",
                                                                                         (e.Attribute("name") ??
                                                                                          new XAttribute("name", "")).
                                                                                             Value.replace(
                                                                                             "[PM]:" +
                                                                                             normalname.Replace(".",
                                                                                                                @"\.") +
                                                                                             @"\.", "")),
                                                                          e.Elements()
                                                          )
                                             )
                                ));
                        desc.Documentation = xdoc;
                        log.Info("type added: "+desc.Type.FullName);
                        MyQuery.ConfiguredTypes.Add(desc.Type);
                        MyQuery.Types[ns].Add(desc);
                    }
                }
            }
            base.internalProcess(query);
        }
    }
}